﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using CCWin;
using System.IO;
using CCWin.SkinControl;
using GroupChat2013.Entity;
using CCWin.Win32;
using GroupChat2013.Logic.Interface;
using GroupChat2013.Logic;
using GroupChat2013.Interface;
using System.Threading;
using System.Collections;
using GroupChat2013.Logic.Message;
using GroupChat2013.Main.Controls;
using GroupChat2013.Common;
using GroupChat2013.Service;
using System.Runtime.Remoting.Messaging;
using GroupChat2013.Data;
using GroupChat2013.Main.Properties;
using System.Web;

namespace GroupChat2013.Main
{
    public partial class FrmGroup : CCSkinMain, IChat, IGroupChat
    {
        #region 变量

        /// <summary>
        /// 群内好友
        /// </summary>
        private ChatListItem ListItem;

        /// <summary>
        /// 当前登录用户
        /// </summary>
        public UserInfo m_CurrentUser
        {
            get { return EngineContext.Current.CurrUserInfo; }
        }

        /// <summary>
        /// 所在群信息
        /// </summary>
        private GroupInfo m_GroupInfo;

        /// <summary>
        /// 消息管理
        /// </summary>
        private GroupChat2013.Interface.IMessage m_ChatMessage;

        private ObjTalker m_ObjTalker;

        /// <summary>
        /// 记录最近聊天信息
        /// </summary>
        private RecChatRepository m_RecChatRepository;

        private bool m_HasItem = true;

        private AutoResetEvent m_AutoReset = new AutoResetEvent(false);

        /// <summary>
        /// 发送聊天信息队列
        /// </summary>
        private Queue m_MessageQueue;

        /// <summary>
        /// 发送信息线程
        /// </summary>
        private Thread m_SendThread;

        /// <summary>
        /// 服务代理
        /// </summary>
        private ServiceUrlProxy m_ServiceUrlProxy = ServiceUrlProxy.GetInstance();

        private ChatConfigInfo configInfo;

        private FrmChatRecord frmChatRecord;

        #endregion

        #region 事件


        #endregion

        #region 构造函数

        public FrmGroup(GroupInfo groupInfo)
        {
            InitializeComponent();
            m_GroupInfo = groupInfo;

            //创建消息处理
            m_ChatMessage = new GroupMessage(EngineContext.Current.CurrUserInfo, m_GroupInfo.groupId);

            chatPanel.messageManage = m_ChatMessage;

            m_ObjTalker = new ObjTalker() { TypeChat = ChatType.Group, GroupInfo = m_GroupInfo };

            this.chatPanel.CreateMsgAfter += new ChatPanel.CreateMsgEventHandler(chatPanel_CreateMsgAfter);
            this.chatPanel.DragDrop += new DragEventHandler(chatPanel_DragDrop);
            this.chatPanel.DragEnter += new DragEventHandler(chatPanel_DragEnter);
            this.chatPanel.SendFile += (s, data) =>
            {
                foreach (string filePath in data)
                {
                    FileSend(filePath);
                }
            };

            //点击聊天记录按钮
            this.chatPanel.ChatRecordClickedHandler += () =>
            {
                //string url = ServiceUrlProxy.GetInstance().UserChatMsgURL(m_CurrentUser.UserName, m_CurrentUser.CID, m_FriendInfo.userInfoId);
                //FrmGroup.OpenWithChrome(url);

                if (frmChatRecord == null || frmChatRecord.IsDisposed)
                {
                    frmChatRecord = new FrmChatRecord(m_ChatMessage, ChatType.Group, groupInfo.groupId, groupInfo.groupName);
                    frmChatRecord.Show(new Rectangle(this.Location, new Size(this.Width, this.Height)));
                }
                else frmChatRecord.Close();
            };

            this.chatPanel.SendKeyDownHandler += new KeyEventHandler(chatPanel_SendKeyDownHandler);

            this.btnSend.ButtonClick += new EventHandler(btnSend_ButtonClick);
            this.FormClosing += new FormClosingEventHandler(FrmGroup_FormClosing);
            this.FormClosed += new FormClosedEventHandler(FrmGroup_FormClosed);
            this.Activated += new EventHandler(FrmGroup_Activated);

            this.tsbSendFile.Click += new EventHandler(tsbSendFile_Click);

            this.flashTimer.Tick += new EventHandler(flashTimer_Tick);
            this.Load += new EventHandler(FrmGroup_Load);
            this.Move += new EventHandler(FrmChat_Move);
        }

        private void FrmChat_Move(object sender, EventArgs e)
        {
            if (frmChatRecord != null && !frmChatRecord.IsDisposed)
            {
                frmChatRecord.SetLocation(new Rectangle(this.Location, new Size(this.Width, this.Height)));
            }
        }

        #endregion

        #region 加载公告、好友

        /// <summary>
        /// 设置公告
        /// </summary>
        public void SetNoticeContent()
        {
            try
            {
                AsyncClient.AsyncCall<List<Notice>>(() =>
                {
                    Thread.Sleep(500);
                    return m_ServiceUrlProxy.GetGroupNotice(m_GroupInfo.groupId, m_CurrentUser.CID, 0, 1);
                },
                (notices) =>
                {
                    if (notices != null)
                    {
                        stbGroupNotice.SkinTxt.Text = notices.Count == 0 || string.IsNullOrEmpty(notices[0].groupContent) ?
                            "暂无公告！" : notices[0].groupContent;
                    }
                    else
                    {
                        stbGroupNotice.SkinTxt.Text = "暂无公告！";
                    }
                });
            }
            catch { stbGroupNotice.SkinTxt.Text = "暂无公告！"; }
        }

        /// <summary>
        /// 更新群用户列表
        /// </summary>
        public void UpdateUserListInfo()
        {
            try
            {
                AsyncClient.AsyncCall<List<FriendInfo>>(() =>
                {
                    ListItem.SubItems.Clear();
                    return m_ServiceUrlProxy.GetGroupUserList(m_GroupInfo.groupId, m_CurrentUser.CID);
                },
                (friendList) =>
                {
                    if (friendList != null && friendList.Count > 0)
                    {
                        friendList.ForEach(x =>
                        {
                            ChatListSubItem subItem = new ChatListSubItem(x.userInfoId, x.loginName, x.loginName, "", ChatType.User);
                            subItem.HeadImage = Image.FromFile(GroupChat2013.Common.Helper.CombinePath(@"head\1.png"));
                            if (x.online)
                                subItem.Status = ChatListSubItem.UserStatus.Online;
                            else
                                subItem.Status = ChatListSubItem.UserStatus.OffLine;

                            ListItem.SubItems.AddAccordingToStatus(subItem);
                        });
                    }
                });
            }
            catch { }
        }

        #endregion

        #region 根据配置加载顶部按钮

        public void InitGroupButtonList()
        {
            AsyncClient.AsyncCall<List<ButtonConfigInfo>>(() =>
            {
                GroupButtonConfigParse appConfigParse = new GroupButtonConfigParse();
                return appConfigParse.Parse();
            },
            (configInfoList) =>
            {
                List<ToolStripItem> items = new List<ToolStripItem>();

                for (int i = 0; i < configInfoList.Count; i++)
                {
                    string name = "tsButton" + i;
                    items.Add(CreateToolStripButton(configInfoList[i], name));
                }

                this.skinToolStrip2.Items.AddRange(items.ToArray());
            });
        }

        private ToolStripButton CreateToolStripButton(ButtonConfigInfo configInfo, string name)
        {
            ToolStripButton button = new ToolStripButton();
            button.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
            button.Image = string.IsNullOrEmpty(configInfo.imgNormal) ? (Image)Resources.default_ButtonImg : Image.FromFile(configInfo.imgNormal);
            button.ImageTransparentColor = System.Drawing.Color.Magenta;
            button.Name = name;
            button.Size = new System.Drawing.Size(45, 31);
            button.Text = configInfo.desc;
            button.ToolTipText = configInfo.tip;

            button.Click += (s, e) =>
            {
                string gname = HttpUtility.UrlEncode(m_GroupInfo.groupName);

                string url = string.Format("{0}?cid={1}&gId={2}&gName={3}"
                     , configInfo.link, m_CurrentUser.CID, m_GroupInfo.groupId, gname);

                FrmGroup.OpenWithChrome(url);
            };

            return button;
        }

        #endregion

        #region 发送消息相关

        /// <summary>
        /// 初始化队列
        /// </summary>
        private void InitSendQueue()
        {
            m_MessageQueue = Queue.Synchronized(new Queue());
            m_SendThread = new Thread(new ThreadStart(() =>
            {
                while (m_HasItem)
                {
                    if (m_MessageQueue.Count > 0)
                    {
                        SendMessage sendMessage = m_MessageQueue.Dequeue() as SendMessage;
                        if (sendMessage != null)
                        {
                            SendChatMessage(sendMessage);
                        }
                    }
                    else
                    {
                        m_AutoReset.WaitOne();
                    }
                }
            }));
            m_SendThread.IsBackground = true;
            m_SendThread.Start();
        }

        /// <summary>
        /// 发送消息
        /// </summary>
        /// <param name="content"></param>
        /// <param name="appendAction"></param>
        private void SendChatMessage(SendMessage sendMessage)
        {
            List<MessageInfo> mcList = m_ChatMessage.SendMessage(sendMessage.MessageContent, sendMessage.ImagePathList, m_CurrentUser.CID);

            this.BeginInvoke(new Action(() =>
            {
                //加入消息记录区
                //this.chatPanel.SendToRichTextBox(sendMessage.MessageContent, true);
                this.chatPanel.ClearSendImageCache();

                //发送成功后将接收到的信息添加到消息记录区
                if (mcList != null && mcList.Count > 0)
                {
                    mcList.ForEach(x =>
                    {
                        if (x.MessageContent.FromId == m_CurrentUser.UserId)
                            this.chatPanel.SendToRichTextBox(sendMessage.MessageContent, true);
                        else
                            this.chatPanel.ReceiveToRichTextBox(x.MessageContent);
                    });
                }
                else //发送失败
                {
                    chatPanel.WriteNoticeToRichTextBox("消息发送失败！  " + sendMessage.MessageContent.Content);
                }
            }));

            //添加到最近聊天记录
            AddRecChat();
        }

        /// <summary>
        /// 将消息添加到队列中
        /// </summary>
        /// <param name="content"></param>
        private void EnqueueMessage(SendMessage sendMessage)
        {
            m_MessageQueue.Enqueue(sendMessage);
            m_AutoReset.Set();
        }

        private void btnSend_ButtonClick(object sender, EventArgs e)
        {
            this.chatPanel.SendMsg();
        }

        /// <summary>
        /// 快捷键发送
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void chatPanel_SendKeyDownHandler(object sender, KeyEventArgs e)
        {
            bool canSend = false;
            if (btnSend.SendMode == SendMode.ENTER)
            {
                canSend = e.KeyValue == 13;
            }
            else if (btnSend.SendMode == SendMode.CTRLENTER)
            {
                canSend = e.Control && e.KeyValue == 13;
            }
            else if (btnSend.SendMode == SendMode.ALTS)
            {
                canSend = e.Alt && e.KeyValue == 83;
            }

            if (canSend)
            {
                this.chatPanel.SendMsg();

                e.Handled = true;
            }
        }

        #endregion

        #region 当消息创建后发送到服务器

        private void chatPanel_CreateMsgAfter(object sender, MessageContent msg)
        {
            msg.FromId = m_CurrentUser.UserId;
            msg.FromName = m_CurrentUser.UserName;

            List<MyPicture> pictures = this.chatPanel.GetSendPicture();
            List<string> imageList = new List<string>();
            if (pictures != null)//如果文件是截图
            {
                //x.MD5.Length == 32 表示是截图或者插入的图片，因为
                //保存的图片名称是GUID 长度32
                pictures.ForEach(x => { if (x.MD5.Length == 32) imageList.Add(x.MD5); });
            }

            SendMessage sm = new SendMessage() { ImagePathList = imageList, MessageContent = msg };
            EnqueueMessage(sm);
            this.chatPanel.ClearSendMsgTextBox();
        }

        #endregion

        #region 接收服务器的聊天信息

        /// <summary>
        /// 更新聊天信息
        /// </summary>
        public void UpdateChatMessage()
        {
            AsyncClient.AsyncCall<List<MessageInfo>>(() =>
            {
                return m_ChatMessage.ReceiverMessage(m_CurrentUser.CID);
            },
            (mcList) =>
            {
                this.BeginInvoke(new Action(() =>
                {
                    mcList.ForEach(x =>
                    {
                        chatPanel.ReceiveToRichTextBox(x.MessageContent);
                    });

                    if (mcList != null && mcList.Count > 0 &&
                        WinApi.GetActiveWindow() != this.Handle)
                    {
                        MyFlashWindow(this, true);
                    }
                }));

                //添加到最近聊天记录
                AddRecChat();
            });
        }

        #endregion

        #region 文件发送

        private void chatPanel_DragEnter(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(DataFormats.Text))
                e.Effect = DragDropEffects.All;
            else if (e.Data.GetDataPresent(DataFormats.FileDrop))
                e.Effect = DragDropEffects.All;
        }

        private void chatPanel_DragDrop(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop))
            {
                string[] MyFiles;
                int i;
                // 将文件赋给一个数组。
                MyFiles = (string[])(e.Data.GetData(DataFormats.FileDrop));
                // 循环处理数组并将文件添加到列表中。
                for (i = 0; i <= MyFiles.Length - 1; i++)
                {
                    System.IO.FileInfo f = new System.IO.FileInfo(MyFiles[i]);
                    if (f.Exists)
                    {
                        if (!FileSend(f.FullName))
                        {
                            return;
                        }
                    }
                }
            }
        }

        #endregion

        #region 窗体事件

        /// <summary>
        /// 窗口加载时
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void FrmGroup_Load(object sender, EventArgs e)
        {
            this.uploadPanel.m_OrgX = 10;
            this.uploadPanel.m_OrgY = 1;

            ListItem = new ChatListItem("群成员");
            ListItem.IsOpen = true;
            ListItem.IsTwinkleHide = true;
            chatShow.Items.Add(ListItem);

            UpdateUserListInfo();

            TopMost = false;
            this.Location = Program.GetLocation(this.Width, this.Height);
            lblChatQm.Text = m_GroupInfo.groupDesc;
            lblGroupName.Text = m_GroupInfo.groupName;

            SetNoticeContent();
            //UpdateUserListInfo();

            InitSendQueue();

            this.chatPanel.InitDownloadImgQueue();

            this.UpdateChatMessage();

            InitChatConfig();

            InitGroupButtonList();

            //通知窗体已经打开
            EngineContext.Current.ChatManager.NoticeChatOpened(m_GroupInfo.groupId);

            tsbGroup_ButtonClick(tsbGroup, null);
        }

        private void InitChatConfig()
        {
            ChatConfigInfo configInfo = EngineContext.Current.ChatConfig.Parse();
            this.chatPanel.SetFontStyle(configInfo);
            this.btnSend.configInfo = configInfo;
            this.btnSend.SendMode = (SendMode)Enum.Parse(typeof(SendMode), configInfo.SendMode.ToString());
        }

        /// <summary>
        /// 窗体关闭时
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void FrmGroup_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (uploadPanel.ControlCount > 0)
            {
                DialogResult result = MessageBoxEx.Show("如果关闭窗口，将会中止文件传输。是否关闭窗口？", "提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Information);
                if (result == DialogResult.OK)
                {
                    uploadPanel.CancelAllUpload();

                    e.Cancel = false;
                }
                else
                    e.Cancel = true;
            }
        }

        /// <summary>
        /// 关闭窗体后
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void FrmGroup_FormClosed(object sender, FormClosedEventArgs e)
        {
            EngineContext.Current.ChatManager.RemoveChat(m_GroupInfo.groupId);

            if (ListItem != null && ListItem.SubItems.Count > 0)
            {
                ListItem.SubItems.Clear();
                ListItem = null;
            }

            this.chatPanel.Release();

            try
            {
                m_SendThread.Abort();
            }
            catch { }
            m_MessageQueue.Clear();

            EngineContext.Current.ChatConfig.SaveConfig();

            if (frmChatRecord != null && !frmChatRecord.IsDisposed)
            {
                frmChatRecord.Close();
            }

            GC.Collect();
        }

        //关闭
        private void btnClose_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        //渐变层
        private void FrmGroup_Paint(object sender, PaintEventArgs e)
        {
            Graphics g = e.Graphics;
            SolidBrush sb = new SolidBrush(Color.FromArgb(150, 255, 255, 255));
            g.FillRectangle(sb, new Rectangle(new Point(1, 91), new Size(Width - 2, Height - 91 - 33)));
        }

        #endregion

        #region 接受消息任务栏闪烁

        private void flashTimer_Tick(object sender, EventArgs e)
        {
            WinApi.FlashWindow(this.Handle, true);
        }

        private void FrmGroup_Activated(object sender, EventArgs e)
        {
            flashTimer.Enabled = false;

            InitChatConfig();
        }

        public void MyFlashWindow(Form window, bool invert)
        {
            flashTimer.Enabled = true;
        }

        #endregion

        #region 公共方法


        #endregion

        #region 私有方法

        //文件发送方法
        private bool FileSend(string filePath)
        {
            tsbUploadFile_ButtonClick(tsbUploadFile, null);

            return uploadPanel.AddUploadItem(filePath, m_ObjTalker, (shareResultInfo) =>
              {
                  chatPanel.WriteNoticeToRichTextBox(shareResultInfo.CompeledStr);

                  if (shareResultInfo.IsSucess || !string.IsNullOrEmpty(shareResultInfo.downloadUrl))
                  {
                      MessageContent msg = new MessageContent();
                      msg.Content = m_CurrentUser.UserName + "分享了文件" + shareResultInfo.downloadUrl;//获得消息文本内容
                      msg.ContentUrl = shareResultInfo.downloadUrl;
                      msg.FromId = m_CurrentUser.UserId;
                      msg.FromName = m_CurrentUser.UserName;
                      m_ChatMessage.SendMessage(msg, null, m_CurrentUser.CID);
                  }
              });
        }

        #endregion

        #region 实现 IChat接口

        /// <summary>
        /// 更新会话
        /// </summary>
        public void UpdateChat()
        {
            this.UpdateChatMessage();
        }

        /// <summary>
        /// 链接成功
        /// </summary>
        public void ConnectionSucc()
        {
            this.Enabled = true;
        }

        /// <summary>
        /// 连接失败
        /// </summary>
        public void ConnectionFail()
        {
            this.Enabled = false;
        }

        #endregion

        #region 实现 IGroupChat接口

        public void UpdateUserList()
        {
            UpdateUserListInfo();
        }

        public void UpdateNotice()
        {
            SetNoticeContent();
        }

        public void UpdateDetail()
        {
            
        }

        /// <summary>
        /// 更新用户在线状态
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="status">1在线 0 离线</param>
        public void UpdateUserStatus(string userId, int status)
        {
            foreach (ChatListSubItem item in ListItem.SubItems)
            {
                if (item.ID.Equals(userId))
                {
                    item.Status = status == 1 ? CCWin.SkinControl.ChatListSubItem.UserStatus.Online :
                        CCWin.SkinControl.ChatListSubItem.UserStatus.OffLine;

                    chatShow.Update();
                    return;
                }
            }
        }

        #endregion

        #region 窗口右侧控件相关事件

        /// <summary>
        /// 搜索控件文字改变事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void txtSearch_TextChanged(object sender, EventArgs e)
        {
            if (string.IsNullOrEmpty(txtSearch.Text))
            {
                GroupSearchShow.Visible = false;
                return;
            }

            List<ChatListSubItem> groupItemList = chatShow.GetSubItemsByDisplayName(txtSearch.Text);

            GroupSearchShow.Items.Clear();
            ChatListItem groupItem = new ChatListItem("搜索结果");
            groupItem.IsOpen = true;
            groupItem.SubItems.AddRange(groupItemList.ToArray());
            GroupSearchShow.Items.Add(groupItem);

            GroupSearchShow.Visible = true;
        }

        /// <summary>
        /// 双击搜索结果好友
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void GroupSearchShow_DoubleClickSubItem(object sender, ChatListEventArgs e)
        {
            ChatListSubItem item = e.SelectSubItem;
            item.IsTwinkle = false;

            if (item.ID == m_CurrentUser.UserId)
                return;

            FrmMain.ShowFrmChat(item);
        }
        
        /// <summary>
        /// 选中了文件发送选项卡
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void tsbUploadFile_ButtonClick(object sender, EventArgs e)
        {
            tsbGroup.BackgroundImage = null;
            tsbUploadFile.BackgroundImage = Resources.tabBg;

            uploadPanel.Visible = true;
            spGroup.Visible = false;
        }

        /// <summary>
        /// 选择了群内信息选项卡
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void tsbGroup_ButtonClick(object sender, EventArgs e)
        {
            tsbGroup.BackgroundImage = Resources.tabBg;
            tsbUploadFile.BackgroundImage = null;

            uploadPanel.Visible = false;
            spGroup.Visible = true;
        }

        /// <summary>
        /// 双击打开用户
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void chatShow_DoubleClickSubItem(object sender, ChatListEventArgs e)
        {
            ChatListSubItem item = e.SelectSubItem;
            item.IsTwinkle = false;

            if (item.ID == m_CurrentUser.UserId)
                return;

            FrmMain.ShowFrmChat(item);
        }

        #endregion

        #region 窗体上侧控件相关事件

        /// <summary>
        /// 发送文件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void tsbSendFile_Click(object sender, EventArgs e)
        {
            OpenFileDialog Dlg = new OpenFileDialog();
            FileInfo fileInfo;
            Dlg.Filter = "所有文件(*.*)|*.*";
            Dlg.CheckFileExists = true;

            if (Dlg.ShowDialog() == DialogResult.OK)
            {
                fileInfo = new FileInfo(Dlg.FileName);
                FileSend(fileInfo.FullName);

                tsbUploadFile_ButtonClick(tsbUploadFile, null);
            }
        }

        public static bool OpenWithChrome(string url)
        {
            string path = GroupChat2013.Common.Helper.GetChromePath();
            if (string.IsNullOrEmpty(path))
            {
                MessageBoxEx.Show("请到下载中心下载可用的Chrome浏览器",
                    "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return false;
            }

            System.Diagnostics.Process.Start("CHROME.EXE", url);
            return true;
        }

        #endregion

        #region 添加到最近聊天

        public void AddRecChat()
        {
            if (m_RecChatRepository == null)
                m_RecChatRepository = new RecChatRepository(EngineContext.Current.FilePathManager.DbPath);

            RecChatInfo chatInfo = new RecChatInfo()
            {
                ChatId = m_GroupInfo.groupId,
                ChatName = m_GroupInfo.groupName,
                NickName = string.Empty,
                ChatType = ChatType.Group,
                HeadUrl = string.Empty,
                CreateTime = DateTime.Now
            };

            m_RecChatRepository.AddRecChatInfo(chatInfo);
        }

        #endregion

    }
}
